package com.king.hpeproject.service;

import com.king.hpeproject.constant.CommonConstant;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.security.Key;


@Slf4j
@Component
public class JwtService {
    /**
     * Token 过期时间： 一小时
     */
    @Value("${jwt.token.expire-time}")
    private Long EXPIRE_TIME;
    /**
     * Token生成的密钥
     */
    @Value("${jwt.token.secret}")
    private String SECRET;

    /**
     * JWT内容的键
     */
    public static final String CLAIM_SESSION_ID = "sessionId";
    public static final String CLAIM_EXPIRE_TIME = "exp";
    public static final String CLAIM_USER_ID = "userId";
    public static final String CLAIM_USER_NAME = "userName";
    public static final String CLAIM_SN = "sn";
    /**
     * Token 无痛刷新的过渡时间
     *      刷新Token的区间 = 【过期时间 - 过渡时间， 过期时间】
     */
    public static final Long REFRESH_TRANSITION_TIME = 1000L * 60 * 60;
    public static final Integer TOKEN_VALIDATED = 1;
    public static final Integer TOKEN_REQUIRE_FRESH = 2;
    public static final Integer TOKEN_EXPIRED = 3;

    /**
     * 解析Token，获取Token的负载。
     * @param token 接收到的Token字符串
     * @return 返回claims
     */
    public Claims getClaimsFromToken(String token){
        Key key = Keys.hmacShaKeyFor(Decoders.BASE64.decode(SECRET));
        return Jwts.parserBuilder()
                .setSigningKey(key)
                .build()
                .parseClaimsJws(token)
                .getBody();
    }

    /**
     * 解析Token, 拿到UserId
     * @param request 带有Token的HTTP请求
     * @return userId
     */
    public Long getUserIdFromToken(HttpServletRequest request){
        return getPropertyFromToken(request.getHeader(CommonConstant.HEADER_TOKEN.getCode()));
    }

    /**
     * 获取Token中的属性
     *
     * @param token token字符串
     * @return 属性值，如果不存在该键，返回null
     */
    private <T> T getPropertyFromToken(String token){
        try {
            Claims claims = getClaimsFromToken(token);
            return claims.get(JwtService.CLAIM_USER_ID, (Class<T>) Long.class);
        } catch (JwtException | ClassCastException e) {
            log.error(e.getMessage(), e);
            return null;
        } catch (IllegalArgumentException illegalArgumentException) {
            log.error("getPropertyFromToken illegalArgumentException", illegalArgumentException);
            return null;
        }
    }
}
